#include <QDebug>
#include <QRegExp>

#include "defines.h"
#include "maemo5defines.h"
#include "maemo5statusupdater.h"

#define PROGRESS_MAX 1000

Maemo5StatusUpdater::Maemo5StatusUpdater(Maemo5QtProjectGenerator & generator,
                                         QObject                  * parent)
    : IStatusUpdater(parent),
      m_generator(generator)
{
    // Connect generator messages
    connect(&m_generator,
            SIGNAL(started(GeneratorTarget)),
            this,
            SLOT(start(GeneratorTarget)));
    connect(&m_generator,
            SIGNAL(finished(int)),
            this,
            SLOT(stop()));
    connect(&(m_generator.outputView()),
            SIGNAL(message(QString)),
            this,
            SLOT(increase(QString)));

    // Some defaults if others are not provided
    m_phasesInAction = 10;
    m_maximumValue = PROGRESS_MAX;
    m_lastLogCounter = 0;

    // Reset values that can be changed outside
    reset();
}

Maemo5StatusUpdater::~Maemo5StatusUpdater()
{
    ;
}


void Maemo5StatusUpdater::updateGeneratorStatus(bool manualTrigger)
{
    // If progress is indefinite, we're doing some time consuming
    // task with indefinite progress, so do not update the status.
    if (m_indefinite)
        return;

    GeneratorPhase phase = m_generator.getCurrentPhase();

    if (phase == M5_ENDED_SUCCESSFULLY || phase == M5_ENDED_WITH_ERRORS)
    {
        m_currentValue = m_maximumValue;
        m_statusText = m_generator.getStatusText();
        emit updated();
        emit finished(phase == M5_ENDED_SUCCESSFULLY);
    }
    else if (!manualTrigger)
    {
        // Progressbar steps in phase
        int phaseStep = m_maximumValue / m_phasesInAction;

        // Progressbar steps in one message. Phases have very different amount of messages,
        // so we'll calculate an approximation for this.
        int messageStep = phaseStep / phaseLength(phase);
        int currentValue = m_currentValue;
        int nextPhaseStart = (currentValue / phaseStep + 1) * phaseStep;

        if (phase != m_lastPhase)
        {
            // Set the progressbar to the beginning of the next step
            m_statusText = m_generator.getStatusText();
            m_currentValue = nextPhaseStart;
            emit updated();
        }
        else
        {
            // Update at every step, but only up to the next phase's start
            if ((currentValue + messageStep) < nextPhaseStart)
            {
                m_currentValue = currentValue + messageStep;
                emit updated();
            }
        }
    }

    m_lastPhase = phase;
}


void Maemo5StatusUpdater::setIndefiniteProgress(bool indefinite)
{
    m_indefinite = indefinite;
}


void Maemo5StatusUpdater::setPhases(int phases)
{
    m_phasesInAction = phases;
}


void Maemo5StatusUpdater::reset()
{
    m_currentValue = 0;
    m_logSize = 0;
    m_phase = M5_INITIAL;
    m_lastPhase = M5_INITIAL;
    m_statusText = m_generator.getStatusText();
    m_indefinite = false;
    emit updated();
}


int Maemo5StatusUpdater::maximumProgress()
{
    return m_maximumValue;
}


int Maemo5StatusUpdater::currentProgress()
{
    return m_currentValue;
}


QString Maemo5StatusUpdater::statusText()
{
    return m_statusText;
}


int Maemo5StatusUpdater::logSize()
{
    return m_logSize;
}


QFileInfo Maemo5StatusUpdater::pkgFileInfo()
{
    QFileInfo
        rv;

    // sample pattern to look for, as .deb file has the same
    // base name:
    // dpkg-genchanges  >../stew_0.0.1-1_armel.changes

    // Look for the deb (.changes) file name in the lastlog
    QRegExp rx;
    rx.setPattern(".*dpkg-genchanges  >\\.\\./([^ ]+armel)\\.changes.*");
    for (int i = 0;i < LASTLOG_ITEMS; i++)
    {
        qDebug() << "CHECK ---- " << m_lastLog[i];
        if (rx.indexIn(m_lastLog[i]) != -1)
        {
            qDebug() << "Match!";
            QString
                pkgFile(m_generator.generatorData().projectDirectory() + "/" + rx.cap(1));
            pkgFile += ".deb";
            QFileInfo info(pkgFile);
            qDebug() << "Found generated deb file:" << info.canonicalFilePath();
            if (info.exists())
            {
                qDebug() << "Exists!";
                rv = info;
                break;
            }
            else
            {
                qDebug() << "Does not exist!";
                break;
            }
        }
    }

    return rv;
}


void Maemo5StatusUpdater::increase(QString message)
{
    // Set the last log messages to an array
    m_lastLog[m_lastLogCounter] = message;
    m_lastLogCounter = (m_lastLogCounter + 1) % LASTLOG_ITEMS;

    // See if progress is on and status should be updated
    if (m_phasesInAction > 0)
        {
                m_logSize++;
                updateGeneratorStatus(false);
        }
}


void Maemo5StatusUpdater::start(GeneratorTarget target)
{
    reset();

    switch (target)
    { // TODO REMOVE PREVIEW - it will never happen
    case PREVIEW:
        m_phasesInAction = 3;
        break;
    case BUILD:
        m_phasesInAction = 9; // TODO much less phases - how many
        break;
    case REBUILD:
        m_phasesInAction = 8; // TODO much less phases - how many?
        break;
    default:
        m_indefinite = true;
        break;
    }
}


void Maemo5StatusUpdater::stop()
{
    updateGeneratorStatus(true);
}


int Maemo5StatusUpdater::phaseLength(GeneratorPhase phase)
{
    switch (phase.m_phase)
    {
    case M5_INITIAL:
            return 1; // TODO check value
    case M5_UNZIP_WIDGET:
            return 150; // TODO check value
    case M5_DPKG_BUILDPACKAGE:
            return 6; // TODO check value !!!!
    case M5_ENDED_SUCCESSFULLY:
            return 1; // TODO check value
    case M5_ENDED_WITH_ERRORS:
            return 1; // TODO check value
    default:
            return 10; // TODO check value
    }
}


